home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / PROG_TOO / C027B.ZIP / TOP / DATA.C < prev    next >
Text File  |  1990-03-30  |  9KB  |  354 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * Routines for data flow analysis of a single instruction
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18. /*
  19.  * idata
  20.  *
  21.  * For each instruction, we have some global information, as well
  22.  * as flags indicating what the instruction does with its operands.
  23.  * We need to know if each operand is set and/or referenced. If the
  24.  * instruction has side-effects not directly related to its operands,
  25.  * we need to know that as well, so "special case" code can deal with
  26.  * that as well.
  27.  */
  28. struct    idata    {
  29.  
  30.     char    iflag;        /* flags regarding the entire instruction */
  31. #define        SIDE    0x01    /* inst. has side-effects */
  32. #define        CC    0x02    /* inst. munges condition codes */
  33.  
  34.     char    op1f;        /* flags for the first and second operands */
  35.     char    op2f;
  36. #define        SET    0x01    /* operand is set */
  37. #define        REF    0x02    /* operand is referenced */
  38.  
  39. } idata[] =
  40. {
  41.     { CC,        REF,        REF|SET },    /* OR */
  42.     { CC,        REF,        REF },        /* BTST */
  43.     { 0,        REF,        SET },        /* MOVEP */
  44.     { CC,        REF,        REF|SET },    /* BCHG */
  45.     { CC,        REF,        REF|SET },    /* BCLR */
  46.     { CC,        REF,        REF|SET },    /* BSET */
  47.     { CC,        REF,        REF|SET },    /* AND */
  48.     { CC,        REF,        REF|SET },    /* SUB */
  49.     { CC,        REF,        REF|SET },    /* ADD */
  50.     { CC,        REF,        REF|SET },    /* EOR */
  51.     { CC,        REF,        REF },        /* CMP */
  52.     { CC,        REF,        SET },        /* MOVE */
  53.     { CC,        REF|SET,    0 },        /* NEGX */
  54.     { CC,        REF,        REF },        /* CHK */
  55.     { 0,        REF,        SET },        /* LEA */
  56.     { CC,        SET,        0 },        /* CLR */
  57.     { CC,        REF|SET,    0 },        /* NEG */
  58.     { CC,        REF|SET,    0 },        /* NOT */
  59.     { CC,        REF|SET,    0 },        /* NBCD */
  60.     { CC,        REF|SET,    0 },        /* SWAP */
  61.     { SIDE,        REF,        0 },        /* PEA */
  62.     { CC,        REF|SET,    0 },        /* EXT */
  63.     { SIDE,        REF,        SET },        /* MOVEM */
  64.     { CC,        REF,        0 },        /* TST */
  65.     { CC,        REF|SET,    0 },        /* TAS */
  66.     { 0,        REF,        0 },        /* TRAP */
  67.     { SIDE,        REF|SET,    REF },        /* LINK */
  68.     { SIDE,        REF|SET,    0 },        /* UNLK */
  69.     { 0,        0,        0 },        /* RESET */
  70.     { 0,        0,        0 },        /* NOP */
  71.     { CC,        REF,        0 },        /* STOP */
  72.     { SIDE|CC,    0,        0 },        /* RTE */
  73.     { SIDE,        0,        0 },        /* RTS */
  74.     { 0,        0,        0 },        /* TRAPV */
  75.     { SIDE|CC,    0,        0 },        /* RTR */
  76.     { SIDE,        REF,        0 },        /* JSR */
  77.     { 0,        REF,        0 },        /* JMP */
  78.     { CC,        REF,        REF|SET },    /* ADDQ */
  79.     { 0,        SET,        0 },        /* ST */
  80.     { CC,        REF|SET,    REF },        /* DBT */
  81.     { CC,        REF,        REF|SET },    /* SUBQ */
  82.     { 0,        SET,        0 },        /* SF */
  83.     { CC,        REF|SET,    REF },        /* DBRA (dbf) */
  84.     { 0,        SET,        0 },        /* SHI */
  85.     { CC,        REF|SET,    REF },        /* DBHI */
  86.     { 0,        SET,        0 },        /* SLS */
  87.     { CC,        REF|SET,    REF },        /* DBLS */
  88.     { 0,        SET,        0 },        /* SCC */
  89.     { CC,        REF|SET,    REF },        /* DBCC */
  90.     { 0,        SET,        0 },        /* SCS */
  91.     { CC,        REF|SET,    REF },        /* DBCS */
  92.     { 0,        SET,        0 },        /* SNE */
  93.     { CC,        REF|SET,    REF },        /* DBNE */
  94.     { 0,        SET,        0 },        /* SEQ */
  95.     { CC,        REF|SET,    REF },        /* DBEQ */
  96.     { 0,        SET,        0 },        /* SVC */
  97.     { CC,        REF|SET,    REF },        /* DBVC */
  98.     { 0,        SET,        0 },        /* SVS */
  99.     { CC,        REF|SET,    REF },        /* DBVS */
  100.     { 0,        SET,        0 },        /* SPL */
  101.     { 0,        SET,        0 },        /* SMI */
  102.     { CC,        REF|SET,    REF },        /* DBMI */
  103.     { 0,        SET,        0 },        /* SGE */
  104.     { CC,        REF|SET,    REF },        /* DBGE */
  105.     { 0,        SET,        0 },        /* SLT */
  106.     { CC,        REF|SET,    REF },        /* DBLT */
  107.     { 0,        SET,        0 },        /* SGT */
  108.     { CC,        REF|SET,    REF },        /* DBGT */
  109.     { 0,        SET,        0 },        /* SLE */
  110.     { CC,        REF|SET,    REF },        /* DBLE */
  111.     { 0,        REF,        0 },        /* BRA */
  112.     { SIDE,        REF,        0 },        /* BSR */
  113.     { 0,        REF,        0 },        /* BHI */
  114.     { 0,        REF,        0 },        /* BLS */
  115.     { 0,        REF,        0 },        /* BCC */
  116.     { 0,        REF,        0 },        /* BCS */
  117.     { 0,        REF,        0 },        /* BNE */
  118.     { 0,        REF,        0 },        /* BEQ */
  119.     { 0,        REF,        0 },        /* BVC */
  120.     { 0,        REF,        0 },        /* BVS */
  121.     { 0,        REF,        0 },        /* BPL */
  122.     { 0,        REF,        0 },        /* BMI */
  123.     { 0,        REF,        0 },        /* BGE */
  124.     { 0,        REF,        0 },        /* BLT */
  125.     { 0,        REF,        0 },        /* BGT */
  126.     { 0,        REF,        0 },        /* BLE */
  127.     { CC,        REF,        SET },        /* MOVEQ */
  128.     { CC,        REF,        REF|SET },    /* DIVU */
  129.     { CC,        REF,        REF|SET },    /* SBCD */
  130.     { CC,        REF,        REF|SET },    /* DIVS */
  131.     { CC,        REF,        REF|SET },    /* SUBX */
  132.     { CC,        REF,        REF },        /* CMPM */
  133.     { CC,        REF,        REF|SET },    /* MULU */
  134.     { CC,        REF,        REF|SET },    /* ABCD */
  135.     { 0,        REF|SET,    REF|SET },    /* EXG */
  136.     { CC,        REF,        REF|SET },    /* MULS */
  137.     { CC,        REF,        REF|SET },    /* ADDX */
  138.     { CC,        REF,        REF|SET },    /* ASR */
  139.     { CC,        REF,        REF|SET },    /* LSR */
  140.     { CC,        REF,        REF|SET },    /* ROXR */
  141.     { CC,        REF,        REF|SET },    /* ROR */
  142.     { CC,        REF,        REF|SET },    /* ASL */
  143.     { CC,        REF,        REF|SET },    /* LSL */
  144.     { CC,        REF,        REF|SET },    /* ROXL */
  145.     { CC,        REF,        REF|SET },    /* ROL */
  146.     { 0,        0,        0 },        /* DC */
  147. };
  148.  
  149. /*
  150.  * chkset(op) - check to see if operand 'op' sets a register
  151.  *
  152.  * This given operand is set by an instruction. Depending on the
  153.  * addressing mode used, this may set a register. If so, return
  154.  * an appropriate mask. This only happens with register direct
  155.  * addressing.
  156.  */
  157. int
  158. chkset(op)
  159. struct    opnd    *op;
  160. {
  161.     switch (M(op->amode)) {
  162.  
  163.     case REG:
  164.         return RM(op->areg);
  165.     case REGI:
  166.         if (op->amode & (INC|DEC))
  167.             return RM(op->areg);
  168.         else
  169.             return 0;
  170.  
  171.     default:
  172.         return 0;
  173.     }
  174. }
  175.  
  176. /*
  177.  * chkref(op) - check to see if operand 'op' references a register
  178.  *
  179.  * Checks for register references in source or destination
  180.  * operands, since they can occur in either.
  181.  */
  182. int
  183. chkref(op, is_src)
  184. struct    opnd    *op;
  185. bool    is_src;        /* is the operand a source? */
  186. {
  187.     switch (M(op->amode)) {
  188.  
  189.     case NONE:
  190.     case IMM:
  191.     case ABS:
  192.     case PCD:
  193.         return 0;
  194.  
  195.     case REG:
  196.         if (is_src)
  197.             return RM(op->areg);
  198.         else
  199.             return 0;
  200.  
  201.     case REGI:
  202.     case REGID:
  203.         return RM(op->areg);
  204.  
  205.     case REGIDX:
  206.         return (RM(op->areg) | RM(op->ireg));
  207.  
  208.     case PCDX:
  209.         return RM(op->ireg);
  210.  
  211.     default:
  212.         fprintf(stderr, "illegal mode in chkref() %d\n", M(op->amode));
  213.         exit(1);
  214.     }
  215. }
  216.  
  217. /*
  218.  * chkside(ip, type) - check for side-effects of 'ip'
  219.  *
  220.  * Return a mask of registers set or referenced (depending on 'type')
  221.  * by the given instruction. For example, "pea" sets and references
  222.  * the stack pointer.
  223.  */
  224. int
  225. chkside(ip, type)
  226. INST    *ip;
  227. int    type;
  228. {
  229.     switch (ip->opcode) {
  230.     case PEA:        /* refs/sets the stack pointer */
  231.         return RM(SP);
  232.  
  233.     case LINK:        /* refs/sets SP */
  234.         return RM(SP);
  235.  
  236.     case UNLK:
  237.         if (type == SET)
  238.             return RM(SP);
  239.         else
  240.             return 0;
  241.  
  242.     case RTE:
  243.     case RTS:
  244.     case RTR:
  245.         return RM(SP);
  246.  
  247.     case JSR:
  248.     case BSR:
  249.         /*
  250.          * We have to account, here, for what the called
  251.          * routine might do. Registers D0-3 and A0-3 may
  252.          * be munged.
  253.          */
  254.         if (type == SET)
  255.             return    RM(A0)|RM(A1)|RM(A2)|RM(A3)|
  256.                 RM(D0)|RM(D1)|RM(D2)|RM(D3)|RM(SP);
  257.         else
  258.             return    RM(SP);
  259.  
  260.  
  261.     case MOVEM:
  262.         /*
  263.          * We should really check for a register mask spec.
  264.          * here and parse it. The simple solution is to assume
  265.          * that all the registers used for register variables
  266.          * are referenced or modified.
  267.          */
  268.         return RM(A4)|RM(A5)|RM(A7)|RM(D4)|RM(D5)|RM(D6)|RM(D7);
  269.  
  270.     default:
  271.         fprintf(stderr, "chkside() - unknown opcode\n");
  272.         exit(1);
  273.     }
  274. }
  275.  
  276. /*
  277.  * reg_set(ip) - return mask of regs set by 'ip'
  278.  */
  279. int
  280. reg_set(ip)
  281. INST    *ip;
  282. {
  283.     int    mask = 0;    /* build up a register mask */
  284.  
  285.     if (idata[ip->opcode].op1f & SET)
  286.         mask |= chkset(&ip->src);
  287.     if (idata[ip->opcode].op1f & REF) {
  288.         if ((ip->src.amode & (INC|DEC)) != 0)
  289.             mask |= RM(ip->src.areg);
  290.     }
  291.  
  292.     if (idata[ip->opcode].op2f & SET)
  293.         mask |= chkset(&ip->dst);
  294.     if (idata[ip->opcode].op2f & REF) {
  295.         if ((ip->dst.amode & (INC|DEC)) != 0)
  296.             mask |= RM(ip->dst.areg);
  297.     }
  298.  
  299.     if (idata[ip->opcode].iflag & SIDE)
  300.         mask |= chkside(ip, SET);
  301.  
  302.     return mask;
  303. }
  304.  
  305. /*
  306.  * reg_ref(ip) - return mask of regs referenced by 'ip'
  307.  */
  308. int
  309. reg_ref(ip)
  310. INST    *ip;
  311. {
  312.     int    mask = 0;    /* build up a register mask */
  313.  
  314.     mask |= chkref(&ip->src, idata[ip->opcode].op1f & REF);
  315.     mask |= chkref(&ip->dst, idata[ip->opcode].op2f & REF);
  316.     if (idata[ip->opcode].iflag & SIDE)
  317.         mask |= chkside(ip, REF);
  318.  
  319.     return mask;
  320. }
  321.  
  322. /*
  323.  * sets(ip, reg) - is 'reg' set by the instruction 'ip'?
  324.  */
  325. bool
  326. sets(ip, reg)
  327. INST    *ip;
  328. int    reg;
  329. {
  330.     return ((reg_set(ip) & RM(reg)) != 0);
  331. }
  332.  
  333. /*
  334.  * refs(ip, reg) - is 'reg' referenced by the instruction 'ip'?
  335.  */
  336. bool
  337. refs(ip, reg)
  338. INST    *ip;
  339. int    reg;
  340. {
  341.     return ((reg_ref(ip) & RM(reg)) != 0);
  342. }
  343.  
  344. /*
  345.  * uses(ip, ref) - is 'reg' used by the instruction 'ip'?
  346.  */
  347. bool
  348. uses(ip, reg)
  349. INST    *ip;
  350. int    reg;
  351. {
  352.     return sets(ip, reg) || refs(ip, reg);
  353. }
  354.